﻿Namespace Functions
    Public MustInherit Class MetisResultFunction
        Inherits MetisFunction

        Protected _Action As MetisFunctionAction = MetisFunctionAction.TruncateAndAdd
        Protected _BackupAction As MetisFunctionAction = MetisFunctionAction.TruncateAndAdd
        Protected _Where As String
        Protected _Having As String
        Protected _BackupWhere As String
        Protected _BackupHaving As String
        Protected _UseGroupBy As Boolean
        Protected _UseDistinct As Boolean
        Protected _BackupUseGroupBy As Boolean
        Protected _BackupUseDistinct As Boolean
        Protected WithEvents _Joins As MetisJoinList
        Protected _BackupJoins As MetisJoinList
        Protected WithEvents _OpSets As MetisSetOpList
        Protected _BackupOpSets As MetisSetOpList
        Protected WithEvents _FunctionReferences As MetisRefFunctionList
        Protected _BackupFunctionReferences As MetisRefFunctionList

        Public Shadows Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs)

        Private Sub HandlesFuncRefListChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles _FunctionReferences.ListChanged
            If e.ListChangedType = ComponentModel.ListChangedType.ItemDeleted OrElse e.ListChangedType = ComponentModel.ListChangedType.Reset Then
                If _Joins.Count > 0 Then
                    For i As Integer = _Joins.Count - 1 To 0
                        If _FunctionReferences.IndexOf(_Joins(i).LeftField.Function) < 0 OrElse _
                           _FunctionReferences.IndexOf(_Joins(i).RightField.Function) < 0 Then
                            _Joins.RemoveAt(i)
                        End If
                    Next
                End If
            End If
        End Sub

        Public ReadOnly Property Joins() As MetisJoinList
            Get
                Return _Joins
            End Get
        End Property

        Public ReadOnly Property OpSets() As MetisSetOpList
            Get
                Return _OpSets
            End Get
        End Property

        Public ReadOnly Property FunctionReferences() As MetisRefFunctionList
            Get
                Return _FunctionReferences
            End Get
        End Property

        Public Property Where() As String
            Get
                Return _Where
            End Get
            Set(ByVal value As String)
                _Where = value
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Where"))
            End Set
        End Property

        Public Property Having() As String
            Get
                Return _Having
            End Get
            Set(ByVal value As String)
                _Having = value
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Having"))
            End Set
        End Property

        Public Overrides Sub CheckIsModified()

        End Sub

        Public Overrides Sub Reload()
            If _LoadState <> MetisLoadState.NewDefinition Then
                Dim OraReader As OracleDataReader
                Dim OraCmd As OracleCommand

                _LoadState = MetisLoadState.Loading

                'Dimension base information
                OraCmd = New OracleCommand(String.Format("SELECT name, table_name, description, modified_on, created_on, Namespace_FK, " & _
                                                         "Where_Condition, Having_Condition, Action, use_group_by, use_distinct " & _
                                                         "FROM dam_functions where function_id={0}", _ID), _MetisCore.Connection)
                OraReader = OraCmd.ExecuteReader
                If OraReader.Read Then
                    _Name = OraReader.GetString(0)
                    _Table = _MetisCore.DBTables.FindTable(OraReader.GetString(1))
                    If _Table Is Nothing Then _Table = New DB.DBTable(_MetisCore, OraReader.GetString(1), DB.DBTableType.Table)

                    _Annotation = If(OraReader.IsDBNull(2), "", OraReader.GetString(2))
                    _ModifiedOn = OraReader.GetDateTime(3)
                    _CreatedOn = OraReader.GetDateTime(4)
                    _Namespace = _MetisCore.Namespaces.Find(If(OraReader.IsDBNull(5), -1, OraReader.GetInt32(6)))
                    _Where = If(OraReader.IsDBNull(6), "", OraReader.GetString(6))
                    _Having = If(OraReader.IsDBNull(7), "", OraReader.GetString(7))
                    _Action = OraReader.GetInt32(8)
                    _UseGroupBy = (OraReader.GetInt32(9) <> 0)
                    _UseDistinct = (OraReader.GetInt32(10) <> 0)

                    _BackupName = _Name
                    _BackupAnnotation = _Annotation

                    _BackupHaving = _Having
                    _BackupWhere = _Where
                    _BackupAction = _Action
                    _BackupUseGroupBy = _UseGroupBy
                    _BackupUseDistinct = _UseDistinct


                    OraReader.Close()

                    'Fields
                    OraCmd = New OracleCommand(String.Format("SELECT function_field_id, field_name, field_type, db_field_name, expression, description, " & _
                                                             "dimension_fk, parent_field, modified_on, created_on, number_format, NVL(column_width,64) " & _
                                                             "FROM dam_function_fields WHERE function_fk={0} ORDER BY seq", _ID), _MetisCore.Connection)
                    OraReader = OraCmd.ExecuteReader
                    _Fields.Clear()
                    _BackupFields.Clear()
                    Do While OraReader.Read

                        Dim tmpFieldExpr As String = If(OraReader.IsDBNull(4), "", OraReader.GetString(4))
                        Dim tmpFieldAnnot As String = If(OraReader.IsDBNull(5), "", OraReader.GetString(5))
                        Dim tmpFieldDim As Dimensions.MetisDimension = If(OraReader.IsDBNull(6), Nothing, _MetisCore.Dimensions.Find(OraReader.GetInt32(6)))
                        Dim tmpFieldParent As Integer = If(OraReader.IsDBNull(7), -1, OraReader.GetInt32(7))
                        Dim tmpFieldFormat As String = If(OraReader.IsDBNull(10), "", OraReader.GetString(10))

                        Dim tmpField As New MetisFunctionField(Me, OraReader.GetInt32(0), OraReader.GetString(1), OraReader.GetInt32(2), _
                                                                  OraReader.GetString(3), tmpFieldExpr, tmpFieldAnnot, tmpFieldDim, tmpFieldParent, _
                                                                  OraReader.GetDateTime(8), OraReader.GetDateTime(9), _
                                                                  tmpFieldFormat, OraReader.GetInt32(11))
                        _Fields.Add(tmpField)
                        _BackupFields.Add(tmpField.Clone)
                    Loop

                    'References
                    OraCmd = New OracleCommand(String.Format("SELECT uses_function_fk, pos_x, pos_y, alias, annotation, func_ref_id FROM dam_function_ref " & _
                                                             "WHERE function_fk={0}", _ID), _MetisCore.Connection)
                    OraReader = OraCmd.ExecuteReader
                    _FunctionReferences.Clear()
                    _BackupFunctionReferences.Clear()
                    _UsesFunctions.Clear()
                    Do While OraReader.Read
                        Dim tmpFunc As Core.Functions.MetisFunction = _MetisCore.Functions.Find(OraReader.GetInt32(0))
                        If tmpFunc IsNot Nothing Then
                            _FunctionReferences.Add(New MetisRefFunction(_MetisCore, Me, OraReader.GetInt32(5), tmpFunc, _
                                                                         New System.Drawing.Point(OraReader.GetInt32(1), OraReader.GetInt32(2)), _
                                                                         OraReader.GetString(3)))
                            _BackupFunctionReferences.Add(New MetisRefFunction(_MetisCore, Me, OraReader.GetInt32(5), tmpFunc, _
                                                                               New System.Drawing.Point(OraReader.GetInt32(1), OraReader.GetInt32(2)), _
                                                                               OraReader.GetString(3)))
                            If Not _UsesFunctions.Contains(tmpFunc) Then _UsesFunctions.Add(tmpFunc)
                        End If
                    Loop

                    'Joins
                    OraCmd = New OracleCommand(String.Format("SELECT left_field_fk, right_field_fk, join_type, left_func_ref_fk, right_func_ref_fk " & _
                                                             "FROM dam_function_joins WHERE function_fk={0}", _ID), _MetisCore.Connection)
                    OraReader = OraCmd.ExecuteReader
                    _Joins.Clear()
                    _BackupJoins.Clear()
                    Do While OraReader.Read
                        Dim tmpLeftFuncRef As MetisRefFunction
                        Dim tmpLeftField As MetisFunctionField
                        Dim tmpRightFuncRef As MetisRefFunction
                        Dim tmpRightField As MetisFunctionField


                        For Each refFunc In _FunctionReferences
                            If tmpLeftFuncRef Is Nothing AndAlso refFunc.ID = OraReader.GetInt32(3) Then
                                tmpLeftFuncRef = refFunc
                                If tmpLeftField Is Nothing Then
                                    Try : tmpLeftField = refFunc.ReferencedFunction.Fields.FieldByID(OraReader.GetInt32(0)) : Catch : End Try
                                End If
                            End If

                            If tmpRightFuncRef Is Nothing AndAlso refFunc.ID = OraReader.GetInt32(4) Then
                                tmpRightFuncRef = refFunc
                                If tmpRightField Is Nothing Then
                                    Try : tmpRightField = refFunc.ReferencedFunction.Fields.FieldByID(OraReader.GetInt32(1)) : Catch : End Try
                                End If
                            End If

                            If tmpLeftField IsNot Nothing AndAlso tmpRightField IsNot Nothing Then Exit For
                        Next
                        If tmpLeftField IsNot Nothing AndAlso tmpRightField IsNot Nothing Then
                            _Joins.Add(New MetisJoin(tmpLeftFuncRef, tmpLeftField, tmpRightFuncRef, tmpRightField, OraReader.GetInt32(2), Me))
                            _BackupJoins.Add(New MetisJoin(tmpLeftFuncRef, tmpLeftField, tmpRightFuncRef, tmpRightField, OraReader.GetInt32(2), Me))
                        End If
                    Loop

                    'UsedBy
                    OraCmd = New OracleCommand(String.Format("SELECT DISTINCT function_fk FROM dam_function_ref " & _
                                                             "WHERE uses_function_fk={0}", _ID), _MetisCore.Connection)
                    OraReader = OraCmd.ExecuteReader
                    _UsedByFunctions.Clear()
                    Do While OraReader.Read
                        Dim tmpFunc As Core.Functions.MetisFunction = _MetisCore.Functions.Find(OraReader.GetInt32(0))
                        If tmpFunc IsNot Nothing Then _UsedByFunctions.Add(tmpFunc)
                    Loop

                End If
                OraReader.Close()

                _LoadState = MetisLoadState.Loaded
                _IsModified = False
                _LastUpdate = Date.Now
                'RaiseEvent Loaded(Me)
            End If
        End Sub

    End Class
End Namespace

